big change in how streams are changed, and lots of bugfixes
This commit is contained in:
parent
7b6acc3a64
commit
072c411ac2
|
@ -442,6 +442,7 @@ class QvitterPlugin extends Plugin {
|
|||
function onNoticeSimpleStatusArray($notice, &$twitter_status, $scoped)
|
||||
{
|
||||
|
||||
|
||||
// groups
|
||||
$notice_groups = $notice->getGroups();
|
||||
$group_addressees = false;
|
||||
|
@ -450,13 +451,6 @@ class QvitterPlugin extends Plugin {
|
|||
}
|
||||
$twitter_status['statusnet_in_groups'] = $group_addressees;
|
||||
|
||||
// include the repeat-id, which we need when unrepeating later
|
||||
if(array_key_exists('repeated', $twitter_status) && $twitter_status['repeated'] === true) {
|
||||
$repeated = Notice::pkeyGet(array('profile_id' => $scoped->id,
|
||||
'repeat_of' => $notice->id));
|
||||
$twitter_status['repeated_id'] = $repeated->id;
|
||||
}
|
||||
|
||||
// more metadata about attachments
|
||||
|
||||
// get all attachments first, and put all the extra meta data in an array
|
||||
|
@ -541,6 +535,7 @@ class QvitterPlugin extends Plugin {
|
|||
$twitter_status['in_reply_to_profileurl'] = null;
|
||||
}
|
||||
|
||||
|
||||
// fave number
|
||||
$faves = Fave::byNotice($notice);
|
||||
$favenum = count($faves);
|
||||
|
@ -550,7 +545,9 @@ class QvitterPlugin extends Plugin {
|
|||
$repeats = $notice->repeatStream();
|
||||
$repeatnum=0;
|
||||
while ($repeats->fetch()) {
|
||||
$repeatnum++;
|
||||
if($repeats->verb == ActivityVerb::SHARE) { // i.e. not deleted repeats
|
||||
$repeatnum++;
|
||||
}
|
||||
}
|
||||
$twitter_status['repeat_num'] = $repeatnum;
|
||||
|
||||
|
@ -724,17 +721,6 @@ class QvitterPlugin extends Plugin {
|
|||
|
||||
assert($notice->id > 0); // since we removed tests below
|
||||
|
||||
// don't add notifications for activity type notices
|
||||
if($notice->source == 'activity' || $notice->object_type == 'activity' || $notice->object_type == 'http://activitystrea.ms/schema/1.0/activity') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// mark reply/mention-notifications as read if we're replying to a notice we're notified about
|
||||
if($notice->reply_to) {
|
||||
self::markNotificationAsSeen($notice->reply_to,$notice->profile_id,'mention');
|
||||
self::markNotificationAsSeen($notice->reply_to,$notice->profile_id,'reply');
|
||||
}
|
||||
|
||||
// repeats
|
||||
if ($notice->isRepeat()) {
|
||||
$repeated_notice = Notice::getKV('id', $notice->repeat_of);
|
||||
|
@ -744,44 +730,57 @@ class QvitterPlugin extends Plugin {
|
|||
// mark reply/mention-notifications as read if we're repeating to a notice we're notified about
|
||||
self::markNotificationAsSeen($repeated_notice->id,$notice->profile_id,'mention');
|
||||
self::markNotificationAsSeen($repeated_notice->id,$notice->profile_id,'reply');
|
||||
|
||||
// (no other notifications repeats)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// replies and mentions (no notifications for these if this is a repeat)
|
||||
else {
|
||||
$reply_notification_to = false;
|
||||
// check for reply to insert in notifications
|
||||
if($notice->reply_to) {
|
||||
try {
|
||||
$replyauthor = $notice->getParent()->getProfile();
|
||||
$reply_notification_to = $replyauthor->id;
|
||||
$this->insertNotification($replyauthor->id, $notice->profile_id, 'reply', $notice->id);
|
||||
//} catch (NoParentNoticeException $e) { // TODO: catch this when everyone runs latest GNU social!
|
||||
// This is not a reply to something (has no parent)
|
||||
} catch (NoResultException $e) {
|
||||
// Parent author's profile not found! Complain louder?
|
||||
common_log(LOG_ERR, "Parent notice's author not found: ".$e->getMessage());
|
||||
}
|
||||
// don't add notifications for activity type notices
|
||||
if($notice->source == 'activity' || $notice->object_type == 'activity' || $notice->object_type == 'http://activitystrea.ms/schema/1.0/activity') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for mentions to insert in notifications
|
||||
$mentions = $notice->getReplies();
|
||||
$sender = Profile::getKV($notice->profile_id);
|
||||
$all_mentioned_user_ids = array();
|
||||
foreach ($mentions as $mentioned) {
|
||||
// mark reply/mention-notifications as read if we're replying to a notice we're notified about
|
||||
if($notice->reply_to) {
|
||||
self::markNotificationAsSeen($notice->reply_to,$notice->profile_id,'mention');
|
||||
self::markNotificationAsSeen($notice->reply_to,$notice->profile_id,'reply');
|
||||
}
|
||||
|
||||
// no duplicate mentions
|
||||
if(in_array($mentioned, $all_mentioned_user_ids)) {
|
||||
continue;
|
||||
}
|
||||
$all_mentioned_user_ids[] = $mentioned;
|
||||
|
||||
// only notify if mentioned user is not already notified for reply
|
||||
if($reply_notification_to != $mentioned) {
|
||||
$this->insertNotification($mentioned, $notice->profile_id, 'mention', $notice->id);
|
||||
}
|
||||
// replies and mentions
|
||||
$reply_notification_to = false;
|
||||
// check for reply to insert in notifications
|
||||
if($notice->reply_to) {
|
||||
try {
|
||||
$replyauthor = $notice->getParent()->getProfile();
|
||||
$reply_notification_to = $replyauthor->id;
|
||||
$this->insertNotification($replyauthor->id, $notice->profile_id, 'reply', $notice->id);
|
||||
//} catch (NoParentNoticeException $e) { // TODO: catch this when everyone runs latest GNU social!
|
||||
// This is not a reply to something (has no parent)
|
||||
} catch (NoResultException $e) {
|
||||
// Parent author's profile not found! Complain louder?
|
||||
common_log(LOG_ERR, "Parent notice's author not found: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// check for mentions to insert in notifications
|
||||
$mentions = $notice->getReplies();
|
||||
$sender = Profile::getKV($notice->profile_id);
|
||||
$all_mentioned_user_ids = array();
|
||||
foreach ($mentions as $mentioned) {
|
||||
|
||||
// no duplicate mentions
|
||||
if(in_array($mentioned, $all_mentioned_user_ids)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$all_mentioned_user_ids[] = $mentioned;
|
||||
|
||||
// only notify if mentioned user is not already notified for reply
|
||||
if($reply_notification_to != $mentioned) {
|
||||
$this->insertNotification($mentioned, $notice->profile_id, 'mention', $notice->id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@ class ApiFavsAndRepeatsAction extends ApiPrivateAuthAction
|
|||
$notice->selectAdd('profile_id');
|
||||
$notice->selectAdd('created');
|
||||
$notice->repeat_of = $this->original->id;
|
||||
$notice->verb = ActivityVerb::SHARE;
|
||||
$notice->orderBy('created, id'); // NB: asc!
|
||||
if (!is_null($this->cnt)) {
|
||||
$notice->limit(0, $this->cnt);
|
||||
|
|
|
@ -170,10 +170,11 @@ class ApiQvitterAllFollowingAction extends ApiBareAuthAction
|
|||
$this->max_id
|
||||
);
|
||||
|
||||
while ($group->fetch()) {
|
||||
$groups[] = clone($group);
|
||||
if(!empty($group)) {
|
||||
while ($group->fetch()) {
|
||||
$groups[] = clone($group);
|
||||
}
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
|
|
|
@ -1405,6 +1405,7 @@ body.rtl #footer-spinner-container {
|
|||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
hyphens: auto;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.tooltip-caret {
|
||||
z-index: 10000;
|
||||
|
@ -4165,6 +4166,15 @@ button.shorten:after {
|
|||
top: 20px;
|
||||
}
|
||||
|
||||
#feed-header-inner .loader {
|
||||
position: absolute;
|
||||
right:4px;
|
||||
top:3px;
|
||||
left:auto;
|
||||
margin-left:0;
|
||||
opacity:0.5;
|
||||
}
|
||||
|
||||
.reload-stream {
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
|
|
@ -176,6 +176,7 @@ function getFromAPI(stream, actionOnSuccess) {
|
|||
data = convertEmptyObjectToEmptyArray(data);
|
||||
data = iterateRecursiveReplaceHtmlSpecialChars(data);
|
||||
searchForUserDataToCache(data);
|
||||
searchForUpdatedNoticeData(data);
|
||||
|
||||
actionOnSuccess(data, userArray, request, url);
|
||||
},
|
||||
|
@ -547,42 +548,6 @@ function postActionToAPI(action, actionOnSuccess) {
|
|||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Delete requeet
|
||||
·
|
||||
· @param this_stream_item: jQuery object for stream-item
|
||||
· @param this_action: JQuery object for the requeet-button
|
||||
· @param my_rq_id: the id for the requeet
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function unRequeet(this_stream_item, this_action, my_rq_id) {
|
||||
this_action.children('.with-icn').removeClass('done');
|
||||
this_action.find('.with-icn b').html(window.sL.requeetVerb);
|
||||
this_stream_item.removeClass('requeeted');
|
||||
|
||||
// post unrequeet
|
||||
postActionToAPI('statuses/destroy/' + my_rq_id + '.json', function(data) {
|
||||
if(data) {
|
||||
remove_spinner();
|
||||
this_stream_item.removeAttr('data-requeeted-by-me-id');
|
||||
this_stream_item.children('.queet').children('.context').find('.requeet-text').children('a[data-user-id="' + window.loggedIn.id + '"]').remove();
|
||||
if(this_stream_item.children('.queet').children('.context').find('.requeet-text').children('a').length<1) {
|
||||
this_stream_item.children('.queet').children('.context').remove();
|
||||
}
|
||||
getFavsAndRequeetsForQueet(this_stream_item, this_stream_item.attr('data-quitter-id'));
|
||||
}
|
||||
else {
|
||||
remove_spinner();
|
||||
this_action.children('.with-icn').addClass('done');
|
||||
this_action.find('.with-icn b').html(window.sL.requeetedVerb);
|
||||
this_stream_item.addClass('requeeted');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
|
|
|
@ -619,22 +619,20 @@ function groupProfileCard(groupAlias) {
|
|||
|
||||
function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess) {
|
||||
|
||||
if(!streamObject && !streamObject.stream) {
|
||||
if(!streamObject || !streamObject.stream) {
|
||||
console.log('invalid streamObject, no stream to set!');
|
||||
return;
|
||||
}
|
||||
|
||||
// update the cache for the old stream
|
||||
rememberStreamStateInLocalStorage();
|
||||
|
||||
// remove any old error messages
|
||||
$('.error-message').remove();
|
||||
|
||||
// remember state of old stream (including profile card)
|
||||
rememberStreamStateInLocalStorage();
|
||||
|
||||
// halt interval that checks for new queets
|
||||
window.clearInterval(checkForNewQueetsInterval);
|
||||
|
||||
display_spinner();
|
||||
|
||||
// scroll to top
|
||||
$(window).scrollTop(0);
|
||||
$('body').addClass('androidFix').scrollTop(0).removeClass('androidFix');
|
||||
|
@ -646,14 +644,19 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess
|
|||
$('#feed-body').removeAttr('data-search-page-number');
|
||||
$('#feed-body').removeAttr('data-end-reached');
|
||||
|
||||
// hide new queets bar and reload stream button
|
||||
$('#new-queets-bar-container').addClass('hidden');
|
||||
$('.reload-stream').hide();
|
||||
|
||||
display_spinner('#feed-header-inner');
|
||||
|
||||
// are we just reloading?
|
||||
var weAreReloading = false;
|
||||
if(typeof window.currentStreamObject != 'undefined' && window.currentStreamObject.name == streamObject.name) {
|
||||
if(typeof window.currentStreamObject != 'undefined' && window.currentStreamObject.stream == streamObject.stream) {
|
||||
weAreReloading = true;
|
||||
}
|
||||
|
||||
// remember the most recent stream
|
||||
window.currentStream = streamObject.stream;
|
||||
// remember the most recent stream object
|
||||
window.currentStreamObject = streamObject;
|
||||
|
||||
// set the new streams header
|
||||
|
@ -669,6 +672,10 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess
|
|||
$('#feed-header-inner h2').append('<div id="stream-menu-cog" data-tooltip="' + window.sL.timelineOptions + '"></div>');
|
||||
}
|
||||
|
||||
// subtle animation to show somethings happening
|
||||
$('#feed-header-inner h2').css('opacity','0.2');
|
||||
$('#feed-header-inner h2').animate({opacity:'1'},1000);
|
||||
|
||||
// if we're just reloading, we dont need to:
|
||||
// (1) check if we have a cached version of this stream
|
||||
// (2) remove the stream if we don't
|
||||
|
@ -689,11 +696,18 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess
|
|||
if(haveOldStreamState) {
|
||||
$('.profile-card,.hover-card,.hover-card-caret').remove();
|
||||
$('#feed').before(haveOldStreamState.card);
|
||||
$('#feed-body').html(haveOldStreamState.feed);
|
||||
|
||||
// subtle animation to show somethings happening
|
||||
$('#feed-header-inner h2').css('opacity','0.2');
|
||||
$('#feed-header-inner h2').animate({opacity:'1'},1000);
|
||||
var oldStreamState = $('<div/>').html(haveOldStreamState.feed);
|
||||
|
||||
// if the cached items has data-quitter-id-in-stream attributes, sort them before adding them
|
||||
if(oldStreamState.children('.stream-item[data-quitter-id-in-stream]').length>0) {
|
||||
oldStreamState.sortDivsByAttrDesc('data-quitter-id-in-stream');
|
||||
$('#feed-body').html('');
|
||||
oldStreamState.children('.stream-item[data-quitter-id-in-stream]').appendTo('#feed-body');
|
||||
}
|
||||
else {
|
||||
$('#feed-body').html(haveOldStreamState.feed);
|
||||
}
|
||||
|
||||
// set location bar from stream
|
||||
if(setLocation) {
|
||||
|
@ -717,11 +731,12 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess
|
|||
$('.profile-card,.hover-card,.hover-card-caret').remove();
|
||||
$('#feed').css('opacity',0);
|
||||
$('#feed-body').html('');
|
||||
remove_spinner(); display_spinner(); // display spinner in page header instead feed header
|
||||
}
|
||||
|
||||
// (3) change design immediately to either cached design or logged in user's
|
||||
if(typeof window.oldStreamsDesigns[theUserOrGroupThisStreamBelongsTo(window.currentStream)] != 'undefined') {
|
||||
changeDesign(window.oldStreamsDesigns[theUserOrGroupThisStreamBelongsTo(window.currentStream)]);
|
||||
if(typeof window.oldStreamsDesigns[window.currentStreamObject.nickname] != 'undefined') {
|
||||
changeDesign(window.oldStreamsDesigns[window.currentStreamObject.nickname]);
|
||||
}
|
||||
else {
|
||||
changeDesign({backgroundimage:window.loggedIn.background_image, backgroundcolor:window.loggedIn.backgroundcolor, linkcolor:window.loggedIn.linkcolor});
|
||||
|
@ -732,7 +747,7 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess
|
|||
getFromAPI(streamObject.stream, function(queet_data, userArray, error, url){
|
||||
|
||||
// while waiting for this data user might have changed stream, so only proceed if current stream still is this one
|
||||
if(window.currentStream != streamObject.stream) {
|
||||
if(window.currentStreamObject.stream != streamObject.stream) {
|
||||
console.log('stream has changed, aborting');
|
||||
return;
|
||||
}
|
||||
|
@ -801,7 +816,9 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess
|
|||
else if(error.status == 410 && streamObject.name == 'notice') {
|
||||
showErrorMessage(window.sL.ERRORnoticeRemoved);
|
||||
}
|
||||
else if(error.status == 0) {
|
||||
else if(error.status == 0
|
||||
|| (error.status == 200 && error.responseText == 'An error occurred.')
|
||||
) {
|
||||
showErrorMessage(window.sL.ERRORnoContactWithServer + ' (' + replaceHtmlSpecialChars(error.statusText) + ')');
|
||||
}
|
||||
else {
|
||||
|
@ -851,13 +868,48 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess
|
|||
addStreamToHistoryMenuAndMarkAsCurrent(streamObject);
|
||||
|
||||
remove_spinner();
|
||||
$('#feed-body').html(''); // empty feed body
|
||||
$('#new-queets-bar').parent().addClass('hidden'); document.title = window.siteTitle; // hide new queets bar if it's visible there
|
||||
addToFeed(queet_data, false,'visible'); // add stream items to feed element
|
||||
$('#feed').animate({opacity:'1'},150); // fade in
|
||||
|
||||
// some streams, e.g. /statuses/show/1234.json is not enclosed in an array, make sure it is
|
||||
if(!$.isArray(queet_data)) {
|
||||
queet_data = [queet_data];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// empty feed-body if this is a
|
||||
// (1) notice page
|
||||
// (2) if we got an empty result
|
||||
// (3) it's not a stream of notices or notifications
|
||||
if(window.currentStreamObject.name == 'notice'
|
||||
|| queet_data.length==0
|
||||
|| (window.currentStreamObject.type != 'notices' && window.currentStreamObject.type != 'notifications')) {
|
||||
$('#feed-body').html('');
|
||||
}
|
||||
// if the last item in the stream doesn't exists in the feed-body, we can't
|
||||
// just prepend the new items, since it will create a gap in the middle of the
|
||||
// feed. in that case we just empty the body and start from scratch
|
||||
else if($('#feed-body').children('.stream-item[data-quitter-id-in-stream="' + queet_data.slice(-1)[0].id + '"]').length == 0) {
|
||||
$('#feed-body').html('');
|
||||
}
|
||||
|
||||
// if the stream is slow to load, the user might have expanded a notice, or scrolled down
|
||||
// and started reading. in that case we add the new items _hidden_
|
||||
if($('#feed-body').children('.stream-item.expanded').length>0 || $(window).scrollTop() > 50) {
|
||||
addToFeed(queet_data, false,'hidden');
|
||||
maybeShowTheNewQueetsBar();
|
||||
}
|
||||
else {
|
||||
addToFeed(queet_data, false,'visible');
|
||||
}
|
||||
|
||||
|
||||
// fade in if we need too
|
||||
if(parseInt($('#feed').css('opacity'),10) == '0') {
|
||||
$('#feed').animate({opacity:'1'},150);
|
||||
}
|
||||
|
||||
$('.reload-stream').show();
|
||||
$('body').removeClass('loading-older');$('body').removeClass('loading-newer');
|
||||
$('html,body').scrollTop(0); // scroll to top
|
||||
|
||||
// maybe do something
|
||||
if(typeof actionOnSuccess == 'function') {
|
||||
|
@ -1028,36 +1080,8 @@ function expand_queet(q,doScrolling) {
|
|||
q.addClass('expanded');
|
||||
q.prev().addClass('next-expanded');
|
||||
|
||||
// if shortened queet, get full text
|
||||
if(q.children('.queet').find('span.attachment.more').length>0 && q.data('attachments') != 'undefined') {
|
||||
|
||||
// get full html for queet, first try localstorage cache
|
||||
var cacheData = localStorageObjectCache_GET('fullQueetHtml',qid);
|
||||
if(cacheData) {
|
||||
q.children('.queet').find('.queet-text').html(cacheData);
|
||||
q.children('.queet').outerHTML(detectRTL(q.children('.queet').outerHTML()));
|
||||
}
|
||||
else {
|
||||
|
||||
var attachmentId = q.children('.queet').find('span.attachment.more').attr('data-attachment-id');
|
||||
|
||||
// the url to the text/html attachment is in an array in an attribute
|
||||
$.each(q.data('attachments'), function(k,attachment) {
|
||||
if(attachment.id == attachmentId) {
|
||||
$.get(attachment.url,function(data){
|
||||
if(data) {
|
||||
// get body and store in localStorage
|
||||
var bodyHtml = $('<html/>').html(data).find('body').html();
|
||||
localStorageObjectCache_STORE('fullQueetHtml',qid,bodyHtml);
|
||||
q.children('.queet').find('.queet-text').html($.trim(bodyHtml));
|
||||
q.children('.queet').outerHTML(detectRTL(q.children('.queet').outerHTML()));
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// get full html, if shortened
|
||||
getFullUnshortenedHtmlForQueet(q);
|
||||
|
||||
// add expanded container
|
||||
var longdate = parseTwitterLongDate(q.find('.created-at').attr('data-created-at'));
|
||||
|
@ -1152,17 +1176,7 @@ function expand_queet(q,doScrolling) {
|
|||
// show inline reply form if logged in
|
||||
if(typeof window.loggedIn.screen_name != 'undefined') {
|
||||
q.children('.queet').append(replyFormHtml(q,qid));
|
||||
|
||||
// if we have cached text, expand the reply form and add that
|
||||
var queetBox = q.children('.queet').find('.queet-box');
|
||||
var cachedText = decodeURIComponent(queetBox.attr('data-cached-text'));
|
||||
var cachedTextText = $('<div/>').html(cachedText).text();
|
||||
if(cachedText != 'undefined') {
|
||||
queetBox.click();
|
||||
queetBox.html(cachedText);
|
||||
setSelectionRange(queetBox[0], cachedTextText.length, cachedTextText.length);
|
||||
queetBox.trigger('input');
|
||||
}
|
||||
maybePrefillQueetBoxWithCachedText(q.children('.queet').find('.queet-box'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1189,15 +1203,22 @@ function cleanUpAfterCollapseQueet(q) {
|
|||
|
||||
/* ·
|
||||
·
|
||||
· Get a queet box, mainly for popups
|
||||
· Get a popup queet box
|
||||
·
|
||||
· @return the html for the queet box
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function queetBoxHtml() {
|
||||
function queetBoxPopUpHtml() {
|
||||
|
||||
// if we have cached text in localstorage
|
||||
var data = localStorageObjectCache_GET('queetBoxInput','pop-up-queet-box');
|
||||
if(data) {
|
||||
var cachedText = encodeURIComponent(data);
|
||||
}
|
||||
|
||||
var startText = encodeURIComponent(window.sL.compose);
|
||||
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 data-tooltip="' + window.sL.tooltipAttachImage + '" class="upload-image"></button><button data-tooltip="' + window.sL.tooltipShortenUrls + '" class="shorten disabled">URL</button></div><div class="queet-button"><span class="queet-counter"></span><button>' + window.sL.queetVerb + '</button></div></div></div>';
|
||||
return '<div class="inline-reply-queetbox"><div id="pop-up-queet-box" class="queet-box queet-box-syntax" data-start-text="' + startText + '" data-cached-text="' + cachedText + '">' + 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 data-tooltip="' + window.sL.tooltipAttachImage + '" class="upload-image"></button><button data-tooltip="' + window.sL.tooltipShortenUrls + '" class="shorten disabled">URL</button></div><div class="queet-button"><span class="queet-counter"></span><button>' + window.sL.queetVerb + '</button></div></div></div>';
|
||||
}
|
||||
|
||||
|
||||
|
@ -1341,28 +1362,14 @@ function showConversation(q, qid, data, offsetScroll) {
|
|||
// note: first we add the full conversation, but hidden
|
||||
if(obj.id != qid) {
|
||||
var queetTime = parseTwitterDate(obj.created_at);
|
||||
|
||||
if(obj.source == 'activity') {
|
||||
|
||||
// because we had an xss issue, the obj.statusnet_html of qvitter-deleted-activity-notices can contain unwanted html, so we escape..
|
||||
obj.statusnet_html = replaceHtmlSpecialChars(obj.statusnet_html);
|
||||
|
||||
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>';
|
||||
|
||||
// detect rtl
|
||||
queetHtml = detectRTL(queetHtml);
|
||||
}
|
||||
else {
|
||||
var queetHtml = buildQueetHtml(obj, obj.id, 'conversation hidden-conversation', false, true);
|
||||
}
|
||||
var queetHtml = buildQueetHtml(obj, obj.id, 'hidden-conversation', false, true);
|
||||
|
||||
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) {
|
||||
if(q.children('.stream-item.conversation[data-quitter-id="' + obj.id + '"]').length > 0) {
|
||||
var streamItemInnerHtml = $('<div/>').append(queetHtml).find('.stream-item').html();
|
||||
q.children('#conversation-stream-item-' + obj.id).html(streamItemInnerHtml);
|
||||
|
||||
q.children('.stream-item.conversation[data-quitter-id="' + obj.id + '"]').html(streamItemInnerHtml);
|
||||
}
|
||||
else if(before_or_after == 'before') {
|
||||
q.children('.queet').before(queetHtml);
|
||||
|
@ -1412,13 +1419,13 @@ function findAndMarkLastVisibleInConversation(streamItem) {
|
|||
|
||||
/* ·
|
||||
·
|
||||
· Recursive walker functions to view onlt reyplies to replies, not full conversation
|
||||
· Recursive walker functions to view only reyplies to replies, not full conversation
|
||||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
function findInReplyToStatusAndShow(q, qid,reply,only_first,onlyINreplyto) {
|
||||
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') + '"]');
|
||||
var reply_found = q.find('.stream-item[data-quitter-id="' + reply + '"]');
|
||||
var reply_found_reply_to = q.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');
|
||||
reply_found.css('opacity','1');
|
||||
|
@ -1490,30 +1497,22 @@ function checkForHiddenConversationQueets(q, qid) {
|
|||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
function addToFeed(feed, after, extraClasses, isReply) {
|
||||
function addToFeed(feed, after, extraClasses) {
|
||||
|
||||
|
||||
// some streams, e.g. /statuses/show/1234.json is not enclosed in an array, make sure it is
|
||||
if(!$.isArray(feed)) {
|
||||
feed = [feed];
|
||||
}
|
||||
|
||||
var addedToTopOfFeedBodyNum = 0;
|
||||
|
||||
$.each(feed.reverse(), function (key,obj) {
|
||||
|
||||
var extraClassesThisRun = extraClasses;
|
||||
|
||||
// is this a temp-post-placeholder?
|
||||
var isTempPost = false;
|
||||
if(after) {
|
||||
if(after.indexOf('stream-item-temp-post') > -1) {
|
||||
isTempPost = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if this is the notifications feed, but not if it is a reply
|
||||
if(window.currentStream.substring(0,35) == 'qvitter/statuses/notifications.json'
|
||||
&& !isReply) {
|
||||
// if this is the notifications feed
|
||||
if(window.currentStreamObject.name == 'notifications') {
|
||||
|
||||
// don't show any notices with object_type "activity"
|
||||
if(typeof obj.notice != 'undefined' && obj.notice !== null && obj.notice.is_activity === true) {
|
||||
|
@ -1526,8 +1525,10 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
obj.from_profile.description = obj.from_profile.description || '';
|
||||
var notificationTime = parseTwitterDate(obj.created_at);
|
||||
|
||||
var notSeenHtml = '';
|
||||
if(obj.is_seen == '0') {
|
||||
extraClassesThisRun = extraClassesThisRun + ' not-seen'
|
||||
extraClassesThisRun += ' not-seen'
|
||||
notSeenHtml = '<div class="not-seen-disc"></div>';
|
||||
}
|
||||
|
||||
// external
|
||||
|
@ -1541,6 +1542,7 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
var noticeTime = parseTwitterDate(obj.notice.created_at);
|
||||
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">\
|
||||
' + notSeenHtml + '\
|
||||
<div class="dogear"></div>\
|
||||
' + ostatusHtml + '\
|
||||
<div class="queet-content">\
|
||||
|
@ -1570,9 +1572,10 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
var noticeTime = parseTwitterDate(obj.notice.created_at);
|
||||
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">\
|
||||
' + notSeenHtml + '\
|
||||
<div class="dogear"></div>\
|
||||
' + ostatusHtml + '\
|
||||
<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 + '" />\
|
||||
|
@ -1610,24 +1613,13 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
}
|
||||
else {
|
||||
$('#feed-body').prepend(notificationHtml);
|
||||
addedToTopOfFeedBodyNum++;
|
||||
}
|
||||
|
||||
// add not seen notification circle
|
||||
$.each($('.notification.not-seen .queet'),function(){
|
||||
if($(this).children('.not-seen').length<1) {
|
||||
$(this).prepend('<div class="not-seen-disc"></div>');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a user feed
|
||||
else if((window.currentStream.substring(0,21) == 'statuses/friends.json'
|
||||
|| window.currentStream.substring(0,18) == 'statuses/followers'
|
||||
|| window.currentStream.substring(0,28) == 'statusnet/groups/membership/'
|
||||
|| window.currentStream.substring(0,24) == 'statusnet/groups/admins/')
|
||||
&& isTempPost === false // not if we're posting queet
|
||||
) {
|
||||
else if(window.currentStreamObject.type == 'users') {
|
||||
|
||||
// only if not user is already in stream
|
||||
if($('#stream-item-' + obj.id).length == 0) {
|
||||
|
@ -1672,14 +1664,13 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
}
|
||||
else {
|
||||
$('#feed-body').prepend(userHtml);
|
||||
addedToTopOfFeedBodyNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a list of groups
|
||||
else if(window.currentStream.substring(0,26) == 'statusnet/groups/list.json'
|
||||
&& isTempPost === false // not if we're posting queet
|
||||
) {
|
||||
else if(window.currentStreamObject.type == 'groups') {
|
||||
|
||||
// only if not group is already in stream
|
||||
if($('#stream-item-' + obj.id).length == 0) {
|
||||
|
@ -1713,41 +1704,19 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
}
|
||||
else {
|
||||
$('#feed-body').prepend(groupHtml);
|
||||
addedToTopOfFeedBodyNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a retweet
|
||||
else if(typeof obj.retweeted_status != 'undefined') {
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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')) {
|
||||
|
||||
// if requeeted before
|
||||
if($('#q-' + obj.retweeted_status.id + ' > .context').find('.requeet-text').length > 0) {
|
||||
// if users rt not already added
|
||||
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>');
|
||||
}
|
||||
}
|
||||
// if no context requeets
|
||||
else {
|
||||
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" data-tooltip="' + parseTwitterDate(obj.created_at) + '"></i><span class="requeet-text"> ' + window.sL.requeetedBy.replace('{requeeted-by}',requeetHtml) + '</span></span></div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
// retweeted object don't exist in feed
|
||||
else {
|
||||
// (note the difference between "the repeat-notice" and "the repeated notice")
|
||||
// but the unrepeat delete activity notices have retweeted_status added to them, so check this is not a delete notice
|
||||
else if(typeof obj.retweeted_status != 'undefined'
|
||||
&& (typeof obj.qvitter_delete_notice == 'undefined' || obj.qvitter_delete_notice === false)) {
|
||||
|
||||
// if repeat-notice doesn't already exist in feed
|
||||
if($('#stream-item-' + obj.id).length == 0) {
|
||||
var queetHtml = buildQueetHtml(obj.retweeted_status, obj.id, extraClassesThisRun, obj);
|
||||
|
||||
if(after) {
|
||||
|
@ -1755,113 +1724,45 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
}
|
||||
else {
|
||||
$('#feed-body').prepend(queetHtml);
|
||||
addedToTopOfFeedBodyNum++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ordinary tweet
|
||||
else {
|
||||
|
||||
// if this is a special qvitter-delete-notice activity notice it means we try to hide
|
||||
// the deleted notice from our stream
|
||||
// the uri is in the obj.text var, between the double curly brackets
|
||||
if(typeof obj.qvitter_delete_notice != 'undefined' && obj.qvitter_delete_notice == true) {
|
||||
var uriToHide = obj.text.substring(obj.text.indexOf('{{')+2,obj.text.indexOf('}}'));
|
||||
var streamItemToHide = $('.stream-item[data-uri="' + uriToHide + '"]');
|
||||
streamItemToHide.animate({opacity:'0.2'},1000,'linear',function(){
|
||||
$(this).css('height',$(this).height() + 'px');
|
||||
$(this).animate({height:'0px'},500,'linear',function(){
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// only if not already exist
|
||||
if($('#q-' + obj.id).length == 0) {
|
||||
if($('#stream-item-' + obj.id).length == 0) {
|
||||
|
||||
// activity get special design
|
||||
if(obj.source == 'activity' || obj.is_activity === true) {
|
||||
|
||||
// because we had an xss issue, the obj.statusnet_html of qvitter-deleted-activity-notices can contain unwanted html, so we escape..
|
||||
obj.statusnet_html = replaceHtmlSpecialChars(obj.statusnet_html);
|
||||
|
||||
var queetTime = parseTwitterDate(obj.created_at);
|
||||
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="' + window.siteInstanceURL + 'notice/' + obj.id + '">' + queetTime + '</a></small></div><div class="queet-text">' + $.trim(obj.statusnet_html) + '</div></div></div></div>';
|
||||
|
||||
// detect rtl
|
||||
queetHtml = detectRTL(queetHtml);
|
||||
|
||||
if(after) {
|
||||
$('#' + after).after(queetHtml);
|
||||
}
|
||||
else {
|
||||
$('#feed-body').prepend(queetHtml);
|
||||
}
|
||||
var queetHtml = buildQueetHtml(obj, obj.id, extraClassesThisRun);
|
||||
|
||||
if(after) {
|
||||
$('#' + after).after(queetHtml);
|
||||
}
|
||||
else {
|
||||
$('#feed-body').prepend(queetHtml);
|
||||
addedToTopOfFeedBodyNum++;
|
||||
|
||||
// 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';
|
||||
});
|
||||
}
|
||||
}
|
||||
// if this is a single notice, we expand it
|
||||
if(window.currentStreamObject.name == 'notice') {
|
||||
expand_queet($('#stream-item-' + obj.id));
|
||||
}
|
||||
|
||||
var queetHtml = buildQueetHtml(obj, obj.id, extraClassesThisRun);
|
||||
|
||||
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 {
|
||||
$('#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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// fadeout any posting-popups
|
||||
setTimeout(function(){
|
||||
$('#popup-sending').fadeOut(1000, function(){
|
||||
$('#popup-sending').remove();
|
||||
});
|
||||
},100);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convertAttachmentMoreHref();
|
||||
});
|
||||
|
||||
convertAttachmentMoreHref();
|
||||
|
||||
// if we've added stuff to the top of feed-body, we update our stream cache
|
||||
if(addedToTopOfFeedBodyNum>0) {
|
||||
rememberStreamStateInLocalStorage();
|
||||
}
|
||||
$('.stream-selection').removeAttr('data-current-user-stream-name'); // don't remeber user feeds
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Build HTML for a queet from an object
|
||||
|
@ -1871,20 +1772,38 @@ function addToFeed(feed, after, extraClasses, isReply) {
|
|||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isConversation) {
|
||||
function buildQueetHtml(obj, idInStream, extraClasses, requeeted_by, isConversation) {
|
||||
|
||||
// if we've blocked this user, but it has slipped through anyway
|
||||
var blockingTooltip = '';
|
||||
if(typeof window.allBlocking != 'undefined') {
|
||||
$.each(window.allBlocking,function(){
|
||||
if(this == obj.user.id){
|
||||
extraClassesThisRun = extraClassesThisRun + ' profile-blocked-by-me';
|
||||
extraClasses += ' profile-blocked-by-me';
|
||||
blockingTooltip = ' data-tooltip="' + window.sL.thisIsANoticeFromABlockedUser + '"';
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// deleted?
|
||||
if(window.knownDeletedNotices[obj.uri]) {
|
||||
|
||||
}
|
||||
// unrepeated?
|
||||
if(typeof requeeted_by != 'undefined' && requeeted_by !== false) {
|
||||
if(window.knownDeletedNotices[requeeted_by.uri]) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// activity? (hidden with css)
|
||||
if(obj.source == 'activity' || obj.is_activity === true) {
|
||||
extraClasses += ' activity';
|
||||
|
||||
// because we had an xss issue with activities, the obj.statusnet_html of qvitter-deleted-activity-notices can contain unwanted html, so we escape, they are hidden anyway
|
||||
obj.statusnet_html = replaceHtmlSpecialChars(obj.statusnet_html);
|
||||
}
|
||||
|
||||
// if we have the full html for a truncated notice cached in localstorage, we use that
|
||||
var cacheData = localStorageObjectCache_GET('fullQueetHtml',obj.id);
|
||||
|
@ -1902,6 +1821,7 @@ function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isCo
|
|||
var idPrepend = '';
|
||||
if(typeof isConversation != 'undefined' && isConversation === true) {
|
||||
var idPrepend = 'conversation-';
|
||||
extraClasses += ' conversation'
|
||||
}
|
||||
|
||||
// is this mine?
|
||||
|
@ -1917,19 +1837,17 @@ function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isCo
|
|||
}
|
||||
|
||||
// requeet html
|
||||
var requeetedClass = '';
|
||||
if(obj.repeated) {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn done"><span class="icon sm-rt" title="' + window.sL.requeetedVerb + '"></span></a></li>';
|
||||
var requeetedClass = 'requeeted';
|
||||
extraClasses += ' requeeted';
|
||||
}
|
||||
else {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn"><span class="icon sm-rt ' + isThisMine + '" title="' + window.sL.requeetVerb + '"></span></a></li>';
|
||||
}
|
||||
// favorite html
|
||||
var favoritedClass = '';
|
||||
if(obj.favorited) {
|
||||
var favoriteHtml = '<a class="with-icn done"><span class="icon sm-fav" title="' + window.sL.favoritedVerb + '"></span></a>';
|
||||
favoritedClass = 'favorited';
|
||||
extraClasses += ' favorited';
|
||||
}
|
||||
else {
|
||||
var favoriteHtml = '<a class="with-icn"><span class="icon sm-fav" title="' + window.sL.favoriteVerb + '"></span></a>';
|
||||
|
@ -2018,25 +1936,40 @@ function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isCo
|
|||
});
|
||||
}
|
||||
|
||||
// requeets
|
||||
// requeets get's a context element and a identifying class
|
||||
// uri used is the repeate-notice's uri for repeats, not the repetED notice's uri (necessary if someone deletes a repeat)
|
||||
var URItoUse = obj.uri;
|
||||
var requeetHtml = '';
|
||||
if(typeof requeeted_by != 'undefined' && requeeted_by !== false) {
|
||||
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" data-tooltip="' + parseTwitterDate(requeeted_by.created_at) + '"></i><span class="requeet-text"> ' + window.sL.requeetedBy.replace('{requeeted-by}',requeetedByHtml) + '</span></span></div>';
|
||||
var URItoUse = requeeted_by.uri;
|
||||
extraClasses += ' is-requeet';
|
||||
}
|
||||
|
||||
// the URI for delete activity notices are the same as the notice that is to be deleted
|
||||
// so we make the URI for the (hidden) actitity notice unique, otherwise we might remove
|
||||
// the activity notice from DOM when we remove the deleted notice
|
||||
if(typeof obj.qvitter_delete_notice != 'undefined' && obj.qvitter_delete_notice == true) {
|
||||
URItoUse += '-activity-notice';
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(typeof requeeted_by != 'undefined' && requeeted_by !== false) {
|
||||
|
||||
}
|
||||
|
||||
// external
|
||||
var ostatusHtml = '';
|
||||
if(obj.is_local === false) {
|
||||
ostatusHtml = '<a target="_blank" data-tooltip="' + window.sL.goToOriginalNotice + '" class="ostatus-link" href="' + obj.external_url + '"></a>';
|
||||
}
|
||||
|
||||
var queetTime = parseTwitterDate(obj.created_at);
|
||||
var queetHtml = '<div \
|
||||
id="' + idPrepend + 'stream-item-' + obj.id + '" \
|
||||
data-uri="' + obj.uri + '" \
|
||||
class="stream-item ' + extraClassesThisRun + ' ' + requeetedClass + ' ' + favoritedClass + '" \
|
||||
id="' + idPrepend + 'stream-item-' + idInStream + '" \
|
||||
data-uri="' + URItoUse + '" \
|
||||
class="stream-item ' + extraClasses + '" \
|
||||
data-attachments=\'' + JSON.stringify(obj.attachments) + '\'\
|
||||
data-source="' + escape(obj.source) + '" \
|
||||
data-quitter-id="' + obj.id + '" \
|
||||
|
@ -2045,7 +1978,7 @@ function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isCo
|
|||
data-in-reply-to-screen-name="' + in_reply_to_screen_name + '" \
|
||||
data-in-reply-to-status-id="' + obj.in_reply_to_status_id + '"\
|
||||
' + requeetedByMe + '>\
|
||||
<div class="queet" id="' + idPrepend + 'q-' + obj.id + '"' + blockingTooltip + '>\
|
||||
<div class="queet" id="' + idPrepend + 'q-' + idInStream + '"' + blockingTooltip + '>\
|
||||
' + requeetHtml + '\
|
||||
' + ostatusHtml + '\
|
||||
<div class="queet-content">\
|
||||
|
|
|
@ -51,35 +51,37 @@
|
|||
|
||||
function localStorageObjectCache_STORE(name, unique_id, object) {
|
||||
|
||||
if(localStorageIsEnabled()) {
|
||||
if(localStorageIsEnabled() === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = localStorageMaybeAppendIdToKey(name);
|
||||
|
||||
if(object === false || object === null || object.length < 1) {
|
||||
// false or an empty object means we remove this entry
|
||||
if(typeof localStorage[name + '-' + unique_id] != 'undefined' && localStorage[name + '-' + unique_id] !== null) {
|
||||
delete localStorage[name + '-' + unique_id];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var dataToSave = {};
|
||||
dataToSave.modified = Date.now();
|
||||
dataToSave.cdata = LZString.compressToUTF16(JSON.stringify(object));
|
||||
|
||||
try {
|
||||
localStorage.setItem(name + '-' + unique_id, JSON.stringify(dataToSave));
|
||||
}
|
||||
catch (e) {
|
||||
if (e.name == 'QUOTA_EXCEEDED_ERR' || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' || e.name == 'QuotaExceededError' || e.name == 'W3CException_DOM_QUOTA_EXCEEDED_ERR') {
|
||||
|
||||
removeOldestLocalStorageEntries(function(){
|
||||
localStorageObjectCache_STORE(name, unique_id, object);
|
||||
});
|
||||
|
||||
if(object === false || object === null || object.length < 1) {
|
||||
// false or an empty object means we remove this entry
|
||||
if(typeof localStorage[name + '-' + unique_id] != 'undefined' && localStorage[name + '-' + unique_id] !== null) {
|
||||
delete localStorage[name + '-' + unique_id];
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
var dataToSave = {};
|
||||
dataToSave.modified = Date.now();
|
||||
dataToSave.cdata = LZString.compressToUTF16(JSON.stringify(object));
|
||||
|
||||
try {
|
||||
localStorage.setItem(name + '-' + unique_id, JSON.stringify(dataToSave));
|
||||
}
|
||||
catch (e) {
|
||||
if (e.name == 'QUOTA_EXCEEDED_ERR' || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' || e.name == 'QuotaExceededError' || e.name == 'W3CException_DOM_QUOTA_EXCEEDED_ERR') {
|
||||
|
||||
removeOldestLocalStorageEntries(function(){
|
||||
localStorageObjectCache_STORE(name, unique_id, object);
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
console.log('could not store in localStorage, unknown error');
|
||||
}
|
||||
}
|
||||
console.log('could not store in localStorage, unknown error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,38 +133,61 @@ function removeOldestLocalStorageEntries(callback) {
|
|||
· · · · · · · · · */
|
||||
|
||||
function localStorageObjectCache_GET(name, unique_id) {
|
||||
if(localStorageIsEnabled()) {
|
||||
if(typeof localStorage[name + '-' + unique_id] != 'undefined' && localStorage[name + '-' + unique_id] !== null) {
|
||||
try {
|
||||
var parsedObject = JSON.parse(localStorage[name + '-' + unique_id]);
|
||||
}
|
||||
catch(e) {
|
||||
return false;
|
||||
}
|
||||
if(typeof parsedObject.modified == 'undefined' || parsedObject.modified === null) {
|
||||
// invalid or old localstorage object found, check the whole localstorage!
|
||||
checkLocalStorage();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var decompressedAndParsed = JSON.parse(LZString.decompressFromUTF16(parsedObject.cdata));
|
||||
return decompressedAndParsed;
|
||||
}
|
||||
catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(localStorageIsEnabled() === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = localStorageMaybeAppendIdToKey(name);
|
||||
|
||||
if(typeof localStorage[name + '-' + unique_id] == 'undefined' || localStorage[name + '-' + unique_id] === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var parsedObject = JSON.parse(localStorage[name + '-' + unique_id]);
|
||||
}
|
||||
catch(e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(typeof parsedObject.modified == 'undefined' || parsedObject.modified === null) {
|
||||
// invalid or old localstorage object found, check the whole localstorage!
|
||||
checkLocalStorage();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var decompressedAndParsed = JSON.parse(LZString.decompressFromUTF16(parsedObject.cdata));
|
||||
return decompressedAndParsed;
|
||||
}
|
||||
else {
|
||||
catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// to the following data types we add the logged in user's user id,
|
||||
// since they contain user specific data (0 for logged out)
|
||||
// selectedLanguage is handled differently, since we want to be able to
|
||||
// access the logged out user's data if we're logged in
|
||||
function localStorageMaybeAppendIdToKey(name) {
|
||||
if(jQuery.inArray(name, ['browsingHistory', 'conversation', 'queetBoxInput', 'streamState']) !== -1) {
|
||||
if(window.loggedIn) {
|
||||
return name + '-' + window.loggedIn.id;
|
||||
}
|
||||
else {
|
||||
return name + '-0' ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkLocalStorage() {
|
||||
|
||||
if(localStorageIsEnabled() === false) {
|
||||
|
@ -246,6 +271,60 @@ function checkLocalStorage() {
|
|||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Checks if localstorage is availible
|
||||
·
|
||||
· We can't just do if(typeof localStorage.selectedLanguage != 'undefined')
|
||||
· because firefox with cookies disabled then freaks out and stops executing js completely
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function localStorageIsEnabled() {
|
||||
var mod = 'test';
|
||||
try {
|
||||
localStorage.setItem(mod, mod);
|
||||
localStorage.removeItem(mod);
|
||||
return true;
|
||||
}
|
||||
catch(e) {
|
||||
if (e.name == 'QUOTA_EXCEEDED_ERR' || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' || e.name == 'QuotaExceededError' || e.name == 'W3CException_DOM_QUOTA_EXCEEDED_ERR') {
|
||||
removeOldestLocalStorageEntries(function(){
|
||||
localStorageIsEnabled();
|
||||
});
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Check for hidden items and show the new queets bar if there are any
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function maybeShowTheNewQueetsBar() {
|
||||
var new_queets_num = $('#feed-body').find('.stream-item.hidden:not(.activity)').length;
|
||||
if(new_queets_num > 0) {
|
||||
|
||||
$('#new-queets-bar').parent().removeClass('hidden');
|
||||
|
||||
// bar label
|
||||
if(new_queets_num == 1) { var q_txt = window.sL.newQueet; }
|
||||
else { var q_txt = window.sL.newQueets; }
|
||||
if(window.currentStreamObject.name == 'notifications') {
|
||||
if(new_queets_num == 1) { var q_txt = window.sL.newNotification; }
|
||||
else { var q_txt = window.sL.newNotifications; }
|
||||
}
|
||||
|
||||
$('#new-queets-bar').html(q_txt.replace('{new-notice-count}',new_queets_num));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
|
@ -568,10 +647,132 @@ function searchForUserDataToCache(obj) {
|
|||
}
|
||||
}
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Iterates recursively through an API response in search for updated notice data
|
||||
· If we find a "repeated" key we assume the parent is a notice object (chosen arbitrary)
|
||||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
|
||||
window.knownDeletedNotices = new Object();
|
||||
function searchForUpdatedNoticeData(obj) {
|
||||
for (var property in obj) {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
if (typeof obj[property] == "object") {
|
||||
searchForUpdatedNoticeData(obj[property]);
|
||||
}
|
||||
else if(typeof obj[property] == 'boolean' && property == 'repeated') {
|
||||
var streamItemFoundInFeed = $('.stream-item[data-conversation-id][data-quitter-id="' + obj.id + '"]'); // data-conversation-id identifies it as a notice, not a user or something
|
||||
|
||||
// if this is a special qvitter-delete-notice activity notice it means we try to hide
|
||||
// the deleted notice from our stream
|
||||
// the uri is in the obj.text var, between the double curly brackets
|
||||
if(typeof obj.qvitter_delete_notice != 'undefined' && obj.qvitter_delete_notice == true) {
|
||||
var uriToHide = obj.text.substring(obj.text.indexOf('{{')+2,obj.text.indexOf('}}'));
|
||||
window.knownDeletedNotices[uriToHide] = true;
|
||||
var streamItemToHide = $('.stream-item[data-uri="' + uriToHide + '"]');
|
||||
slideUpAndRemoveStreamItem(streamItemToHide);
|
||||
}
|
||||
|
||||
// ordinary notices
|
||||
else if(streamItemFoundInFeed.length>0) {
|
||||
|
||||
var queetFoundInFeed = streamItemFoundInFeed.children('.queet');
|
||||
var queetID = streamItemFoundInFeed.attr('data-quitter-id');
|
||||
|
||||
// console.log(obj);
|
||||
|
||||
// sometimes activity notices don't get the is_activity flag set to true
|
||||
// maybe because they were in the process of being saved when
|
||||
// we first got them
|
||||
if(obj.is_activity) {
|
||||
streamItemFoundInFeed.addClass('activity');
|
||||
}
|
||||
|
||||
// update the avatar row if the queet is expanded and the numbers are not the same
|
||||
if(streamItemFoundInFeed.hasClass('expanded')) {
|
||||
var oldFavNum = parseInt(queetFoundInFeed.find('.action-fav-num').text(),10);
|
||||
var oldRQNum = parseInt(queetFoundInFeed.find('.action-rq-num').text(),10);
|
||||
if(oldFavNum != obj.fave_num || oldRQNum != obj.repeat_num) {
|
||||
getFavsAndRequeetsForQueet(streamItemFoundInFeed, queetID);
|
||||
}
|
||||
}
|
||||
|
||||
// avatar may have changed
|
||||
if(typeof obj.user != 'undefined'
|
||||
&& typeof obj.user.profile_image_url_profile_size != 'undefined'
|
||||
&& queetFoundInFeed.find('img.avatar').src != obj.user.profile_image_url_profile_size) {
|
||||
queetFoundInFeed.find('img.avatar').attr('src',obj.user.profile_image_url_profile_size);
|
||||
}
|
||||
|
||||
// name may have changed
|
||||
if(typeof obj.user != 'undefined'
|
||||
&& typeof obj.user.name != 'undefined'
|
||||
&& queetFoundInFeed.find('strong.name').html() != obj.user.name) {
|
||||
queetFoundInFeed.find('strong.name').html(obj.user.name);
|
||||
}
|
||||
|
||||
// set favorite data
|
||||
queetFoundInFeed.find('.action-fav-num').attr('data-fav-num',obj.fave_num);
|
||||
queetFoundInFeed.find('.action-fav-num').html(obj.fave_num);
|
||||
if(obj.favorited) {
|
||||
streamItemFoundInFeed.addClass('favorited');
|
||||
queetFoundInFeed.find('.action-fav-container').children('.with-icn').addClass('done');
|
||||
queetFoundInFeed.find('.action-fav-container').find('.icon.sm-fav').attr('data-tooltip',window.sL.favoritedVerb);
|
||||
}
|
||||
else {
|
||||
streamItemFoundInFeed.removeClass('favorited');
|
||||
queetFoundInFeed.find('.action-fav-container').children('.with-icn').removeClass('done');
|
||||
queetFoundInFeed.find('.action-fav-container').find('.icon.sm-fav').attr('data-tooltip',window.sL.favoriteVerb);
|
||||
}
|
||||
|
||||
// set repeat data
|
||||
queetFoundInFeed.find('.action-rq-num').attr('data-rq-num',obj.repeat_num);
|
||||
queetFoundInFeed.find('.action-rq-num').html(obj.repeat_num);
|
||||
if(obj.repeated) {
|
||||
streamItemFoundInFeed.addClass('requeeted');
|
||||
queetFoundInFeed.find('.action-rt-container').children('.with-icn').addClass('done');
|
||||
queetFoundInFeed.find('.action-rt-container').find('.icon.sm-rt').attr('data-tooltip',window.sL.requeetedVerb);
|
||||
streamItemFoundInFeed.attr('data-requeeted-by-me-id',obj.repeated_id);
|
||||
}
|
||||
else {
|
||||
streamItemFoundInFeed.removeClass('requeeted');
|
||||
queetFoundInFeed.find('.action-rt-container').children('.with-icn').removeClass('done');
|
||||
queetFoundInFeed.find('.action-rt-container').find('.icon.sm-rt').attr('data-tooltip',window.sL.requeetVerb);
|
||||
streamItemFoundInFeed.removeAttr('data-requeeted-by-me-id');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Store the current stream's state (html) in localStorage
|
||||
· Removes a stream item from the feed gracefully
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function slideUpAndRemoveStreamItem(streamItem,callback) {
|
||||
if(streamItem.length>0) {
|
||||
streamItem.animate({opacity:'0.2'},1000,'linear',function(){
|
||||
$(this).css('height',$(this).height() + 'px');
|
||||
$(this).animate({height:'0px'},500,'linear',function(){
|
||||
$(this).remove();
|
||||
if(typeof callback == 'function') {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Store the current stream's state (html) in localStorage (if we're logged in)
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
|
@ -580,17 +781,25 @@ function rememberStreamStateInLocalStorage() {
|
|||
if(typeof window.currentStreamObject != 'undefined') {
|
||||
|
||||
// dont store open conversations, and only store profile card and the top 20 stream-items
|
||||
var firstTwentyHTML = '';
|
||||
$.each($('#feed-body').children('.stream-item').slice(0,20),function(){
|
||||
firstTwentyHTML += $(this).outerHTML();
|
||||
var firstTwentyVisibleHTML = '';
|
||||
var i = 0;
|
||||
$.each($('#feed-body').children('.stream-item'),function(k,streamItem){
|
||||
firstTwentyVisibleHTML += $(streamItem).outerHTML();
|
||||
if(!$(streamItem).hasClass('activity')) {
|
||||
i++;
|
||||
}
|
||||
if(i>20) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
var feed = $('<div/>').append(firstTwentyHTML);
|
||||
var feed = $('<div/>').append(firstTwentyVisibleHTML);
|
||||
feed.find('.view-more-container-top').remove();
|
||||
feed.find('.view-more-container-bottom').remove();
|
||||
feed.find('.stream-item.conversation').remove();
|
||||
feed.find('.expanded-content').remove();
|
||||
feed.find('.inline-reply-queetbox').remove();
|
||||
feed.find('.stream-item').removeClass('expanded').removeClass('next-expanded');
|
||||
feed.find('.not-seen-disc').remove();
|
||||
feed.find('.stream-item').removeClass('expanded').removeClass('next-expanded').removeClass('hidden').addClass('visible');
|
||||
var feedHtml = feed.html();
|
||||
var profileCardHtml = $('#feed').siblings('.profile-card').outerHTML();
|
||||
var streamData = {
|
||||
|
@ -603,6 +812,47 @@ function rememberStreamStateInLocalStorage() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Gets the full unshortened HTML for a queet
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function getFullUnshortenedHtmlForQueet(streamItem) {
|
||||
var queet = streamItem.children('.queet');
|
||||
var queetId = streamItem.attr('data-quitter-id');
|
||||
var attachmentMore = queet.find('span.attachment.more');
|
||||
// only if actually shortened
|
||||
if(attachmentMore.length>0 && streamItem.data('attachments') != 'undefined') {
|
||||
// first try localstorage cache
|
||||
var cacheData = localStorageObjectCache_GET('fullQueetHtml',queetId);
|
||||
if(cacheData) {
|
||||
queet.find('.queet-text').html(cacheData);
|
||||
queet.outerHTML(detectRTL(queet.outerHTML()));
|
||||
}
|
||||
// then try static html file attachment, that we should have in an array in a data-attachments attribute
|
||||
else {
|
||||
var attachmentId = attachmentMore.attr('data-attachment-id');
|
||||
$.each(streamItem.data('attachments'), function(k,attachment) {
|
||||
if(attachment.id == attachmentId) {
|
||||
$.get(attachment.url,function(data){
|
||||
if(data) {
|
||||
// get body and store in localStorage
|
||||
var bodyHtml = $('<html/>').html(data).find('body').html();
|
||||
localStorageObjectCache_STORE('fullQueetHtml',queetId,bodyHtml);
|
||||
queet.find('.queet-text').html($.trim(bodyHtml));
|
||||
queet.outerHTML(detectRTL(queet.outerHTML()));
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Appends a user to the array containing the mentions suggestions to show when typing a notice
|
||||
|
@ -736,27 +986,6 @@ function replaceHtmlSpecialChars(text) {
|
|||
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
}
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Checks if localstorage is availible
|
||||
·
|
||||
· We can't just do if(typeof localStorage.selectedLanguage != 'undefined')
|
||||
· because firefox with cookies disabled then freaks out and stops executing js completely
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function localStorageIsEnabled() {
|
||||
var mod = 'test';
|
||||
try {
|
||||
localStorage.setItem(mod, mod);
|
||||
localStorage.removeItem(mod);
|
||||
return true;
|
||||
}
|
||||
catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
|
@ -873,7 +1102,7 @@ function changeDesign(obj) {
|
|||
|
||||
// if we're logged out and this is the front page, we use the default design
|
||||
if(!window.loggedIn &&
|
||||
(window.currentStream == 'statuses/public_timeline.json' || window.currentStream == 'statuses/public_and_external_timeline.json')) {
|
||||
(window.currentStreamObject.name == 'public timeline' || window.currentStreamObject.name == 'public and external timeline')) {
|
||||
obj.backgroundimage = window.fullUrlToThisQvitterApp + window.siteBackground;
|
||||
obj.backgroundcolor = window.defaultBackgroundColor;
|
||||
obj.linkcolor = window.defaultLinkColor;
|
||||
|
@ -886,8 +1115,8 @@ function changeDesign(obj) {
|
|||
}
|
||||
|
||||
// remember the design for this stream
|
||||
if(typeof window.oldStreamsDesigns[theUserOrGroupThisStreamBelongsTo(window.currentStream)] == 'undefined') {
|
||||
window.oldStreamsDesigns[theUserOrGroupThisStreamBelongsTo(window.currentStream)] = new Object();
|
||||
if(typeof window.oldStreamsDesigns[window.currentStreamObject.nickname] == 'undefined') {
|
||||
window.oldStreamsDesigns[window.currentStreamObject.nickname] = new Object();
|
||||
}
|
||||
|
||||
// change design elements
|
||||
|
@ -898,21 +1127,21 @@ function changeDesign(obj) {
|
|||
else if(obj.backgroundimage.length > 4) {
|
||||
$('body').css('background-image','url(\'' + obj.backgroundimage + '\')');
|
||||
}
|
||||
window.oldStreamsDesigns[theUserOrGroupThisStreamBelongsTo(window.currentStream)].backgroundimage = obj.backgroundimage;
|
||||
window.oldStreamsDesigns[window.currentStreamObject.nickname].backgroundimage = obj.backgroundimage;
|
||||
}
|
||||
if(typeof obj.backgroundcolor != 'undefined') {
|
||||
if(obj.backgroundcolor === false || obj.backgroundcolor == '') {
|
||||
obj.backgroundcolor = window.defaultBackgroundColor;
|
||||
}
|
||||
changeBackgroundColor(obj.backgroundcolor);
|
||||
window.oldStreamsDesigns[theUserOrGroupThisStreamBelongsTo(window.currentStream)].backgroundcolor = obj.backgroundcolor;
|
||||
window.oldStreamsDesigns[window.currentStreamObject.nickname].backgroundcolor = obj.backgroundcolor;
|
||||
}
|
||||
if(typeof obj.linkcolor != 'undefined') {
|
||||
if(obj.linkcolor === false || obj.linkcolor == '') {
|
||||
obj.linkcolor = window.defaultLinkColor;
|
||||
}
|
||||
changeLinkColor(obj.linkcolor);
|
||||
window.oldStreamsDesigns[theUserOrGroupThisStreamBelongsTo(window.currentStream)].linkcolor = obj.linkcolor;
|
||||
window.oldStreamsDesigns[window.currentStreamObject.nickname].linkcolor = obj.linkcolor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1031,7 +1260,7 @@ function detectRTL(s) {
|
|||
$streamItem.find('.queet-text').find('.h-card.mention').prepend('@');
|
||||
$streamItem.find('.queet-text').find('.h-card.group').prepend('!');
|
||||
$streamItem.find('.queet-text').find('.vcard .fn.nickname:not(.group)').prepend('@'); // very old style
|
||||
$streamItem.find('.queet-text').find('.vcard .nickname.mention:not(.fn)').prepend('@'); // old style
|
||||
$streamItem.find('.queet-text').find('.vcard .nickname.mention:not(.fn)').prepend('@'); // old style
|
||||
$streamItem.find('.queet-text').find('.vcard .nickname.group').prepend('!'); // old style
|
||||
$streamItem.find('.queet-text').find('a[rel="tag"]').prepend('#');
|
||||
}
|
||||
|
@ -1401,6 +1630,26 @@ function countCharsInQueetBox(src,trgt,btn) {
|
|||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Prefill the queet box with cached text, if there is any in an attribute
|
||||
·
|
||||
· @param queetBox: jQuery object for the queet box
|
||||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
function maybePrefillQueetBoxWithCachedText(queetBox) {
|
||||
var cachedText = decodeURIComponent(queetBox.attr('data-cached-text'));
|
||||
var cachedTextText = $('<div/>').html(cachedText).text();
|
||||
if(cachedText != 'undefined' && cachedText != 'false') {
|
||||
queetBox.click();
|
||||
queetBox.html(cachedText);
|
||||
setSelectionRange(queetBox[0], cachedTextText.length, cachedTextText.length);
|
||||
queetBox.trigger('input');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Remember my scroll position
|
||||
|
@ -1511,6 +1760,17 @@ jQuery.fn.outerHTML = function(s) {
|
|||
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Sort divs by attribute descending
|
||||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
jQuery.fn.sortDivsByAttrDesc = function sortDivsByAttrDesc(attr) {
|
||||
$("> div", this[0]).sort(dec_sort).appendTo(this[0]);
|
||||
function dec_sort(a, b){ return parseInt($(b).attr(attr),10) > parseInt($(a).attr(attr),10) ? 1 : -1; }
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
|
@ -1661,39 +1921,9 @@ function shortenUrlsInBox(shortenButton) {
|
|||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Return the user screen name that this stream belongs to. last resort just return the stream
|
||||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
function theUserOrGroupThisStreamBelongsTo(stream) {
|
||||
// if screen_name is given as get-var, use that
|
||||
if(stream.indexOf('screen_name=')>-1) {
|
||||
var thisUsersScreenName = stream.substring(stream.indexOf('screen_name=')+12);
|
||||
if(thisUsersScreenName.indexOf('&=')>-1) {
|
||||
thisUsersScreenName = thisUsersScreenName.substring(0,stream.indexOf('&'));
|
||||
}
|
||||
return thisUsersScreenName;
|
||||
}
|
||||
// groups
|
||||
else if(stream.indexOf('statusnet/groups/timeline/')>-1
|
||||
|| stream.indexOf('statusnet/groups/membership/')>-1
|
||||
|| stream.indexOf('statusnet/groups/admins/')>-1) {
|
||||
var groupName = '!' + stream.substring(stream.lastIndexOf('/')+1, stream.indexOf('.json'));
|
||||
return groupName;
|
||||
}
|
||||
// otherwise, and if we're logged in, we assume this is my stream
|
||||
else if (window.loggedIn){
|
||||
return window.loggedIn.screen_name;
|
||||
}
|
||||
else {
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Youtube embed link from youtube url
|
||||
|
|
176
js/qvitter.js
176
js/qvitter.js
|
@ -875,15 +875,8 @@ function doLogin(streamObjectToSet) {
|
|||
|
||||
// we might have cached text for the queet box
|
||||
// (we need to get the mentions suggestions and cache the syntax highlighting before doing this)
|
||||
var cachedQueetBoxData = localStorageObjectCache_GET('queetBoxInput','queet-box');
|
||||
var cachedQueetBoxDataText = $('<div/>').html(cachedQueetBoxData).text();
|
||||
if(cachedQueetBoxData) {
|
||||
queetBox = $('#queet-box');
|
||||
queetBox.click();
|
||||
queetBox.html(cachedQueetBoxData);
|
||||
setSelectionRange(queetBox[0], cachedQueetBoxDataText.length, cachedQueetBoxDataText.length);
|
||||
queetBox.trigger('input');
|
||||
}
|
||||
$('#queet-box').attr('data-cached-text',encodeURIComponent(localStorageObjectCache_GET('queetBoxInput','queet-box')));
|
||||
maybePrefillQueetBoxWithCachedText($('#queet-box'));
|
||||
});
|
||||
|
||||
// load history
|
||||
|
@ -1618,11 +1611,11 @@ $(window).scroll(function() {
|
|||
if($(window).scrollTop() + $(window).height() > $(document).height() - 1000) {
|
||||
|
||||
// not if we're already loading or if no stream is set yet
|
||||
if(!$('body').hasClass('loading-older') && typeof window.currentStream != "undefined" && $('#feed-body').attr('data-end-reached') != 'true') {
|
||||
if(!$('body').hasClass('loading-older') && typeof window.currentStreamObject != "undefined" && $('#feed-body').attr('data-end-reached') != 'true') {
|
||||
$('body').addClass('loading-older');
|
||||
|
||||
// remove loading class in 10 seconds, i.e. try again if failed to load within 10 s
|
||||
if(window.currentStream.substring(0,6) != 'search') {
|
||||
if(window.currentStreamObject.name != 'search') {
|
||||
setTimeout(function(){$('body').removeClass('loading-older');},10000);
|
||||
}
|
||||
|
||||
|
@ -1638,15 +1631,15 @@ $(window).scroll(function() {
|
|||
var searchPage=2;
|
||||
}
|
||||
var nextPage = searchPage+1;
|
||||
var getVars = qOrAmp(window.currentStream) + 'rpp=20&page=' + searchPage; // search uses 'rpp' var and others 'count' for paging, though we can add rrp to others aswell without any problem
|
||||
var getVars = qOrAmp(window.currentStreamObject.stream) + 'rpp=20&page=' + searchPage; // search uses 'rpp' var and others 'count' for paging, though we can add rrp to others aswell without any problem
|
||||
}
|
||||
// normal streams
|
||||
else {
|
||||
var getVars = qOrAmp(window.currentStream) + 'max_id=' + ($('#feed-body').children('.stream-item').last().attr('data-quitter-id-in-stream'));
|
||||
var getVars = qOrAmp(window.currentStreamObject.stream) + 'max_id=' + ($('#feed-body').children('.stream-item').last().attr('data-quitter-id-in-stream'));
|
||||
}
|
||||
|
||||
display_spinner('#footer-spinner-container');
|
||||
getFromAPI(window.currentStream + getVars,function(data){
|
||||
getFromAPI(window.currentStreamObject.stream + getVars,function(data){
|
||||
|
||||
// if data returned an empty array, we have probably reached the bottom
|
||||
if(data.length == 0) {
|
||||
|
@ -1699,41 +1692,24 @@ function checkForNewQueets() {
|
|||
|
||||
// only if logged in and only for notice or notification streams
|
||||
if(window.loggedIn && (window.currentStreamObject.type == 'notices' || window.currentStreamObject.type == 'notifications')) {
|
||||
var lastId = $('#feed-body').children('.stream-item').not('.temp-post').attr('data-quitter-id-in-stream');
|
||||
var addThisStream = window.currentStream;
|
||||
var lastId = $('#feed-body').children('.stream-item').not('.temp-post').not('.posted-from-form').attr('data-quitter-id-in-stream');
|
||||
var addThisStream = window.currentStreamObject.stream;
|
||||
var timeNow = new Date().getTime();
|
||||
getFromAPI(addThisStream + qOrAmp(window.currentStream) + 'since_id=' + lastId,function(data){
|
||||
getFromAPI(addThisStream + qOrAmp(window.currentStreamObject.stream) + 'since_id=' + lastId,function(data){
|
||||
if(data) {
|
||||
$('body').removeClass('loading-newer');
|
||||
if(addThisStream == window.currentStream) {
|
||||
if(addThisStream == window.currentStreamObject.stream) {
|
||||
addToFeed(data, false, 'hidden');
|
||||
|
||||
// if we have hidden items, show new-queets-bar
|
||||
var new_queets_num = $('#feed-body').find('.stream-item.hidden:not(.activity)').length;
|
||||
if(new_queets_num > 0) {
|
||||
|
||||
$('#new-queets-bar').parent().removeClass('hidden');
|
||||
|
||||
// bar label
|
||||
if(new_queets_num == 1) { var q_txt = window.sL.newQueet; }
|
||||
else { var q_txt = window.sL.newQueets; }
|
||||
if(window.currentStreamObject.name == 'notifications') {
|
||||
if(new_queets_num == 1) { var q_txt = window.sL.newNotification; }
|
||||
else { var q_txt = window.sL.newNotifications; }
|
||||
}
|
||||
|
||||
$('#new-queets-bar').html(q_txt.replace('{new-notice-count}',new_queets_num));
|
||||
|
||||
// say hello to the api if this is notifications stream, to
|
||||
// get correct unread notifcation count
|
||||
if(window.currentStreamObject.name == 'notifications') {
|
||||
helloAPI();
|
||||
}
|
||||
|
||||
// cache the now updated stream
|
||||
rememberStreamStateInLocalStorage();
|
||||
// say hello to the api if this is notifications stream, to
|
||||
// get correct unread notifcation count
|
||||
if(window.currentStreamObject.name == 'notifications') {
|
||||
helloAPI();
|
||||
}
|
||||
|
||||
// if we have hidden items, show new-queets-bar
|
||||
maybeShowTheNewQueetsBar()
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2138,9 +2114,9 @@ $('body').on('click','.action-rt-container .icon:not(.is-mine)',function(){
|
|||
getFavsAndRequeetsForQueet(this_stream_item, this_stream_item.attr('data-quitter-id'));
|
||||
|
||||
// mark all instances of this notice as repeated
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').addClass('requeeted');
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').attr('data-requeeted-by-me-id',data.id);
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').children('.queet').find('.action-rt-container').children('.with-icn').addClass('done');
|
||||
$('.stream-item[data-quitter-id="' + data.retweeted_status.id + '"]').addClass('requeeted');
|
||||
$('.stream-item[data-quitter-id="' + data.retweeted_status.id + '"]').attr('data-requeeted-by-me-id',data.id);
|
||||
$('.stream-item[data-quitter-id="' + data.retweeted_status.id + '"]').children('.queet').find('.action-rt-container').children('.with-icn').addClass('done');
|
||||
}
|
||||
else {
|
||||
// error
|
||||
|
@ -2154,13 +2130,34 @@ $('body').on('click','.action-rt-container .icon:not(.is-mine)',function(){
|
|||
else if(this_action.children('.with-icn').hasClass('done')) {
|
||||
display_spinner();
|
||||
|
||||
var my_rq_id = this_stream_item.attr('data-requeeted-by-me-id');
|
||||
unRequeet(this_stream_item, this_action, my_rq_id);
|
||||
var myRequeetID = this_stream_item.attr('data-requeeted-by-me-id');
|
||||
|
||||
// mark all instances of this notice as non-repeated
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').removeClass('requeeted');
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').removeAttr('data-requeeted-by-me-id');
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').children('.queet').find('.action-rt-container').children('.with-icn').removeClass('done');
|
||||
// display button as unrepeated
|
||||
this_action.children('.with-icn').removeClass('done');
|
||||
this_action.find('.with-icn b').html(window.sL.requeetVerb);
|
||||
this_stream_item.removeClass('requeeted');
|
||||
|
||||
// post unrequeet
|
||||
postActionToAPI('statuses/destroy/' + myRequeetID + '.json', function(data) {
|
||||
if(data) {
|
||||
// remove my repeat-notice from the feed, if it's there
|
||||
slideUpAndRemoveStreamItem($('.stream-item[data-quitter-id-in-stream="' + myRequeetID + '"]'));
|
||||
|
||||
// mark all instances of this notice as non-repeated
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').removeClass('requeeted');
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').removeAttr('data-requeeted-by-me-id');
|
||||
$('.stream-item[data-quitter-id="' + this_stream_item.attr('data-quitter-id') + '"]').children('.queet').find('.action-rt-container').children('.with-icn').removeClass('done');
|
||||
|
||||
getFavsAndRequeetsForQueet(this_stream_item, this_stream_item.attr('data-quitter-id'));
|
||||
remove_spinner();
|
||||
}
|
||||
else {
|
||||
remove_spinner();
|
||||
this_action.children('.with-icn').addClass('done');
|
||||
this_action.find('.with-icn b').html(window.sL.requeetedVerb);
|
||||
this_stream_item.addClass('requeeted');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2285,12 +2282,13 @@ $('body').on('click','.action-reply-container',function(){
|
|||
popUpAction('popup-reply-' + this_stream_item_id, window.sL.replyTo + ' ' + this_stream_item.children('.queet').find('.screen-name').html(),replyFormHtml(this_stream_item,this_stream_item_id),queetHtmlWithoutFooter);
|
||||
|
||||
// fix the width of the queet box, otherwise the syntax highlighting break
|
||||
var queetBoxWidth = $('#popup-reply-' + this_stream_item_id).find('.modal-body').find('.inline-reply-queetbox').width()-20;
|
||||
$('#popup-reply-' + this_stream_item_id).find('.modal-body').find('.queet-box-syntax').width(queetBoxWidth);
|
||||
$('#popup-reply-' + this_stream_item_id).find('.modal-body').find('.syntax-middle').width(queetBoxWidth);
|
||||
$('#popup-reply-' + this_stream_item_id).find('.modal-body').find('.syntax-two').width(queetBoxWidth);
|
||||
var queetBox = $('#popup-reply-' + this_stream_item_id).find('.modal-body').find('.inline-reply-queetbox');
|
||||
var queetBoxWidth = queetBox.width()-20;
|
||||
queetBox.children('.queet-box-syntax, .syntax-middle, .syntax-two').width(queetBoxWidth);
|
||||
|
||||
$('#popup-reply-' + this_stream_item_id).find('.modal-body').find('.queet-box').trigger('click'); // expand
|
||||
|
||||
maybePrefillQueetBoxWithCachedText(queetBox.children('.queet-box'));
|
||||
});
|
||||
|
||||
|
||||
|
@ -2301,12 +2299,13 @@ $('body').on('click','.action-reply-container',function(){
|
|||
· · · · · · · · · · · · · */
|
||||
|
||||
$('body').on('click','#top-compose',function(){
|
||||
popUpAction('popup-compose', window.sL.compose,queetBoxHtml(),false);
|
||||
popUpAction('popup-compose', window.sL.compose,queetBoxPopUpHtml(),false);
|
||||
var queetBoxWidth = $('#popup-compose').find('.inline-reply-queetbox').width()-20;
|
||||
$('#popup-compose').find('.queet-box-syntax').width(queetBoxWidth);
|
||||
$('#popup-compose').find('.syntax-middle').width(queetBoxWidth);
|
||||
$('#popup-compose').find('.syntax-two').width(queetBoxWidth);
|
||||
$('#popup-compose').find('.queet-box').trigger('click');
|
||||
maybePrefillQueetBoxWithCachedText($('#popup-compose').find('.queet-box'));
|
||||
});
|
||||
|
||||
|
||||
|
@ -2392,18 +2391,22 @@ $('body').on('click', '.queet-toolbar button',function () {
|
|||
$('.modal-container').remove();
|
||||
|
||||
// try to find a queet to add the temp queet to:
|
||||
var tempQueetInsertedInConversation = false;
|
||||
|
||||
// if the queet is in conversation, add it to parent's conversation
|
||||
if($('.stream-item.replying-to').length > 0 && $('.stream-item.replying-to').hasClass('conversation')) {
|
||||
$('.stream-item.replying-to').parent().append(queetHtml);
|
||||
var insertedTempQueet = $(queetHtml).appendTo($('.stream-item.replying-to').parent());
|
||||
tempQueetInsertedInConversation = true;
|
||||
}
|
||||
// if the queet is expanded, add it to its conversation
|
||||
else if($('.stream-item.replying-to').length > 0 && $('.stream-item.replying-to').hasClass('expanded')) {
|
||||
$('.stream-item.replying-to').append(queetHtml);
|
||||
var insertedTempQueet = $(queetHtml).appendTo($('.stream-item.replying-to'));
|
||||
tempQueetInsertedInConversation = true;
|
||||
}
|
||||
// maybe the replying-to class is missing but we still have a suiting place to add it
|
||||
else if($('.stream-item.expanded[data-quitter-id="' + in_reply_to_status_id + '"]').length > 0) {
|
||||
$('.stream-item.expanded[data-quitter-id="' + in_reply_to_status_id + '"]').append(queetHtml);
|
||||
var insertedTempQueet = $(queetHtml).appendTo($('.stream-item.expanded[data-quitter-id="' + in_reply_to_status_id + '"]'));
|
||||
tempQueetInsertedInConversation = true;
|
||||
}
|
||||
// if we can't find a proper place, add it to top and remove conversation class
|
||||
// if this is either 1) our home/all feed, 2) our user timeline or 3) whole site or 4) whole network
|
||||
|
@ -2411,11 +2414,14 @@ $('body').on('click', '.queet-toolbar button',function () {
|
|||
|| window.currentStreamObject.name == 'my profile'
|
||||
|| window.currentStreamObject.name == 'public timeline'
|
||||
|| window.currentStreamObject.name == 'public and external timeline') {
|
||||
$('#feed-body').prepend(queetHtml.replace('class="stream-item conversation','class="stream-item'));
|
||||
var insertedTempQueet = $(queetHtml).prependTo('#feed-body');
|
||||
insertedTempQueet.removeClass('conversation');
|
||||
}
|
||||
// don't add it to the current stream, open a popup instead, without conversation class
|
||||
else {
|
||||
popUpAction('popup-sending', '',queetHtml.replace('class="stream-item conversation','class="stream-item'),false);
|
||||
popUpAction('popup-sending','','',false);
|
||||
var insertedTempQueet = $(queetHtml).prependTo($('#popup-sending').find('.modal-body'));
|
||||
insertedTempQueet.removeClass('conversation');
|
||||
}
|
||||
|
||||
// maybe post queet in groups
|
||||
|
@ -2443,13 +2449,9 @@ $('body').on('click', '.queet-toolbar button',function () {
|
|||
// post queet
|
||||
postQueetToAPI(queetText, in_reply_to_status_id, postToGroups, function(data){ if(data) {
|
||||
|
||||
// show real queet
|
||||
var new_queet = Array();
|
||||
new_queet[0] = data;
|
||||
addToFeed(new_queet,tempPostId,'visible', true);
|
||||
|
||||
// remove temp queet
|
||||
$('#' + tempPostId).remove();
|
||||
// show real queet and remove temp queet
|
||||
var insertedRealQueet = $(buildQueetHtml(data, data.id, 'visible posted-from-form', false, tempQueetInsertedInConversation)).insertAfter(insertedTempQueet);
|
||||
insertedTempQueet.remove();
|
||||
|
||||
// clear queetbox input cache
|
||||
localStorageObjectCache_STORE('queetBoxInput',queetBox.attr('id'),false);
|
||||
|
@ -2457,6 +2459,13 @@ $('body').on('click', '.queet-toolbar button',function () {
|
|||
// queet count
|
||||
$('#user-queets strong').html(parseInt($('#user-queets strong').html(),10)+1);
|
||||
|
||||
// fadeout any posting-popups
|
||||
setTimeout(function(){
|
||||
$('#popup-sending').fadeOut(1000, function(){
|
||||
$('#popup-sending').remove();
|
||||
});
|
||||
},100);
|
||||
|
||||
}});
|
||||
}
|
||||
});
|
||||
|
@ -2514,7 +2523,6 @@ $('body').on('click','button.shorten',function () {
|
|||
·
|
||||
· · · · · · · · · · · · · */
|
||||
$('body').on('click','.reload-stream',function () {
|
||||
$('.reload-stream').hide();
|
||||
setNewCurrentStream(URLtoStreamRouter(window.location.href),false,false,false);
|
||||
});
|
||||
|
||||
|
@ -2972,15 +2980,29 @@ $('body').on('keyup', 'div.queet-box-syntax', function(e) {
|
|||
· · · · · · · · · · · · · */
|
||||
|
||||
$('body').on('keyup', 'div.queet-box-syntax', function(e) {
|
||||
|
||||
var thisId = $(this).attr('id');
|
||||
var thisText = $.trim($(this).text());
|
||||
|
||||
// keep in global var to avoid doing all these operations every keystroke
|
||||
if(typeof window.queetBoxCurrentlyActive == 'undefined'
|
||||
|| window.queetBoxCurrentlyActive.id != thisId) {
|
||||
window.queetBoxCurrentlyActive = {
|
||||
id: thisId,
|
||||
startText: $.trim($('<div/>').append(decodeURIComponent($(this).attr('data-start-text'))).text()),
|
||||
repliesText: $.trim($('<div/>').append(decodeURIComponent($(this).attr('data-replies-text'))).text())
|
||||
};
|
||||
}
|
||||
|
||||
// remove from cache if empty, or same as default text
|
||||
if($.trim($(this).text()) == ''
|
||||
|| $.trim($(this).text()) == window.sL.compose
|
||||
|| $.trim($(this).text()) == $.trim(decodeURIComponent($(this).attr('data-start-text')))
|
||||
|| $.trim($(this).text()) == $.trim(decodeURIComponent($(this).attr('data-replies-text')))) {
|
||||
localStorageObjectCache_STORE('queetBoxInput',$(this).attr('id'),false);
|
||||
if(thisText == ''
|
||||
|| thisText == window.sL.compose
|
||||
|| thisText == window.queetBoxCurrentlyActive.startText
|
||||
|| thisText == window.queetBoxCurrentlyActive.repliesText) {
|
||||
localStorageObjectCache_STORE('queetBoxInput',thisId,false);
|
||||
}
|
||||
else {
|
||||
localStorageObjectCache_STORE('queetBoxInput',$(this).attr('id'),$(this).html());
|
||||
localStorageObjectCache_STORE('queetBoxInput',thisId,$(this).html());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3122,8 +3144,8 @@ $('body').on('click','.view-more-container-top', function(){
|
|||
$('body').on('click','.show-full-conversation',function(){
|
||||
|
||||
var this_q = $(this).closest('.queet');
|
||||
var this_qid = $(this).closest('.stream-item:not(.conversation)').attr('data-quitter-id');
|
||||
var thisStreamItem = $('#stream-item-' + $(this).attr('data-stream-item-id'));
|
||||
var thisStreamItem = this_q.parent();
|
||||
var this_qid = thisStreamItem.attr('data-quitter-id');
|
||||
|
||||
rememberMyScrollPos(this_q,this_qid);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user